package a02;

public class MinMaxGame<M> implements GameAI<M> {

    @Override
    public M bestMove(Game<M> g) {
	return this.bestMove(g, this.getDepth());
    }

    public M bestMove(Game<M> g, int depth) {
	final byte player = g.currentPlayer();
	int val = Integer.MIN_VALUE;
	M result = null;
	for (M m : g.moves()) {
	    final Game<M> s = g.doMove(m);
	    final int eval = this.evalNextState(s, player, depth - 1);
	    if (eval > val) {
		val = eval;
		result = m;
	    }
	}
	return result;
    }

    @Override
    public Game<M> doBestMove(Game<M> g) {
	return g.doMove(this.bestMove(g));
    }

    public int evalNextState(Game<M> g, byte player, int depth) {
	return this.minmax(g, player, depth);
    }

    public int getDepth() {
	return 12;
    }

    public int minmax(Game<M> g, byte player, int depth) {

	if (depth == 0 || g.ended()) {
	    return g.evalState(player);
	}

	final boolean isMax = g.currentPlayer() == player;

	int resultVal = isMax ? -Integer.MAX_VALUE : Integer.MAX_VALUE;

	for (M m : g.moves()) {

	    final Game<M> child = g.doMove(m);

	    final int nextVal = this.minmax(child, player, depth - 1);

	    if (isMax && nextVal >= resultVal || !isMax && nextVal <= resultVal) {
		resultVal = nextVal;
	    }
	}

	return resultVal;
    }

}
